﻿using System.ComponentModel;
using MadMediaManager.Core.ExtensionMethods;
using MadMediaManager.Core.Properties;

namespace MadMediaManager.Core.Domain.Components
{
    public enum DigitalInformationUnit
    {
        [Description("B")]
        Byte = 0,
        [Description("KB")]
        Kilobyte = 1,
        [Description("MB")]
        Megabyte = 2,
        [Description("GB")]
        Gigabyte = 3
    }

    public class DigitalInformationUnitValue : UnitValue<DigitalInformationUnitValue, DigitalInformationUnit>
    {
        public DigitalInformationUnitValue() { }
        public DigitalInformationUnitValue(DigitalInformationUnit unit, double? value)
        {
            Unit = unit;
            Value = value;
        }

        //This implementation inspired by http://stackoverflow.com/questions/495110/c-datastructure-for-multiple-unit-conversions
        //Example:
        //a: byte
        //b: kilobyte
        //c: megabyte
        //   a     b     c
        //a  1     1/y   1/z
        //b  y     1     1/x
        //c  z     x     1
        private static readonly double[][] ConversionFactors =
            {
                //byte conversions          byte         kilobyte       megabyte                 gigabyte  
                new double[] {              1,           0.0009765625,  0.00000095367431640625,  0.000000000931322574615478515625},
                //kilobyte conversions
                new double[] {              1024,        1,             0.0009765625 ,           0.00000095367431640625},
                //megabyte conversions
                new double[] {              1048576,     1024,          1,                       0.0009765625},
                //gigabyte conversions
                new double[] {              1073741824,  1048576,       1024,                    1}
                
            };

        /// <summary>
        /// Converts the value of this instance to the specified unit and returns a new instance of <see cref="DigitalInformationUnit"/>.
        /// </summary>
        /// <param name="toUnit">The unit to which this <see cref="UnitValue{TUnitValue,TUnit}.Value"/> will be converted</param>
        /// <returns>A new instance housing the converted information</returns>
        public override DigitalInformationUnitValue ConvertTo(DigitalInformationUnit toUnit)
        {
            return new DigitalInformationUnitValue(toUnit, Value * ConversionFactors[(int)Unit][(int)toUnit]);
        }

        private const string ToStringFormat = "{0:0.##} {1}";
        public override string ToString()
        {
            return Value.HasValue
                       ? string.Format(ToStringFormat, Value, Unit.GetDescription())
                       : CoreResources.DigitalInformation_Value_Unkown;
        }
    }
}
